package com.usian.config;

import com.usian.filter.TokenLoginFilter;
import com.usian.filter.TokenVerifyFilter;
import com.usian.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;

@EnableWebSecurity
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserService userService;


    /**
     * configure  AuthenticationManagerBuilder 自动查询用户角色和权限信息
     * HttpSecurity http  自定义登录路径、成功路径
     * (WebSecurity web 静态资源权限
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //配置关于表单登录的内容   FormLoginConfigurer<HttpSecurity>
        //父类中默认进行了配置，我们将其拿到子类，按照自己的需求进行修改
        http
                .authorizeRequests()//进行权限设置
                .mvcMatchers("/logoutSuccess.html")
                .permitAll()
                .anyRequest()//任何请求
                .authenticated()//进行认证
                .and()
                .formLogin()//设置表单登录，后续可以在这里修改自定义登录页面
                .loginPage("/login.html") //设置自定义的登录页面
                .loginProcessingUrl("/login") //指定处理登录请求的路径，对应form表单的action地址
                .permitAll()
                .usernameParameter("username")  //设置登录表单中的账号参数的name，默认为username
                .passwordParameter("password") //设置登录表单中的密码参数的name，默认为password
                //.failureUrl("/error.html") //指定权限认证失败跳转的url路径
                //.defaultSuccessUrl("/main.html", true) //直接访问登录页面，登录成功跳转本url,否则登录成功跳回到登录前访问的地址
                .successHandler(new AuthenticationSuccessHandler() {  //自定义完成登录后逻辑处理
                    //参数authentication：代表登录的用户信息，其中包含如：账号、权限等信息
                    @Override
                    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
                                                        Authentication authentication) throws IOException, ServletException {
                        // TODO 这里你可以根据业务编写登录成功后的业务逻辑代码
                        System.out.println("登录成功1");
                        // 你可以根据实际业务需求，进行自定义转发或重定向
                        request.getSession().getAttribute("sessionkey");

                        //转发
                        //重定向
                        request.getRequestDispatcher("/succList").forward(request, response);
                    }
                })
                .failureHandler(new AuthenticationFailureHandler(){
                    @Override
                    public void onAuthenticationFailure(HttpServletRequest request,
                                                        HttpServletResponse response,
                                                        AuthenticationException e) throws IOException, ServletException {
                        System.out.println("登录失败1");
                        // 你可以根据实际业务需求，进行自定义转发或重定向
                        request.getSession().getAttribute("session");
                        request.getRequestDispatcher("/failList").forward(request, response);
                    }
                })
                .and()
                .addFilter(new TokenLoginFilter(super.authenticationManager())) //认证拦截器
                .addFilter(new TokenVerifyFilter(super.authenticationManager())) //鉴权拦截器
                .rememberMe() //开启记住我
                .and()
                .cors()
                .configurationSource(configurationSource())  //跨域
                .and()
                .logout()
                .logoutUrl("/logout") //退出登录路径
                .logoutSuccessUrl("/logoutSuccess.html")// 设置退出后跳转的路径
                .and().csrf().disable() //禁用csrf功能，这里暂时用不到

        ;
    }

    public CorsConfigurationSource configurationSource() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowedHeaders(Arrays.asList("*"));
        corsConfiguration.setAllowedMethods(Arrays.asList("*"));
        corsConfiguration.setAllowedOrigins(Arrays.asList("*"));
        corsConfiguration.setMaxAge(3600L);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", corsConfiguration);
        return source;
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().
                antMatchers("/bootstrap/**","/css/**","/fonts/**","/img/**","/jquery/**","/script/**","/theme/**","/ztree/**","/layer.js/**");
    }



    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    //jwt 整合 security时 手动显式注入到IOC 容器中
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception
    {
        return super.authenticationManagerBean();
    }

}
